﻿/*
 * Matrix3x4.h
 *
 *  Created on: 2011/06/24
 *      Author: naoki
 */

#ifndef INCLUDED_NTENGINE_MATH_MATRIX3X4_H
#define INCLUDED_NTENGINE_MATH_MATRIX3X4_H

namespace NTEngine {
namespace Math {
class Vector3;
class Quaternion;

/**
 * @brief 3×4行列クラス
 *       多くの場合で4x4の行列は必要ない場合が多いので
 *       データ量のすくないこちらで計算したほうがよいかも
 */
class Matrix3x4 {
public:
	/**
	 * @brief 各成分。最初の数字は行、後ろの数字は列
	 */
	float m11, m12, m13, m14;
	float m21, m22, m23, m24;
	float m31, m32, m33, m34;

	// constructors
	Matrix3x4(){ }
	Matrix3x4( const Matrix3x4& );
	// operators
	void operator*=( const Matrix3x4& );
	float operator()( int row, int column ) const;
	float& operator()( int row, int column );
	bool operator==( const Matrix3x4& m ) const;
	bool operator!=( const Matrix3x4& m ) const;

	/**
	 * @brief 平行移動行列を設定します
	 */
	void setTranslation( float x, float y, float z );

	/**
	 * @brief 平行移動行列を設定します
	 */
	void setTranslation( const Vector3& v );

	/**
	 * @brief X軸回転行列を設定します
	 */
	void setRotationX( float );

	/**
	 * @brief Y軸回転行列を設定します
	 */
	void setRotationY( float );

	/**
	 * @brief Z軸回転行列を設定します
	 */
	void setRotationZ( float );

	/**
	 * @brief スケーリング行列を設定します
	 */
	void setScaling( float xyz );

	/**
	 * @brief スケーリング行列を設定します
	 */
	void setScaling( float x, float y, float z );

	/**
	 * @brief スケーリング行列を設定します
	 */
	void setScaling( const Vector3& v );

	/**
	 * @brief 行列a,bの掛け算の結果を設定します
	 */
	void setMul( const Matrix3x4& a, const Matrix3x4& b );

	/*!
	 * @brief 行列mの逆行列を設定します
	 */
	void setInverse( const Matrix3x4& m );

	/**
	 * @brief 行列mを3x3行列とみなして転置行列を設定します
	 */
	void setTransposed33( const Matrix3x4& m );

	/**
	 * @brief ビュー変換行列を設定します
	 * @param position:カメラ位置
	 * @param target:注視点
	 * @param up:上ベクタ
	 */
	void setViewTransform(
		const Vector3& position,
		const Vector3& target,
		const Vector3& up );

	/**
	 * @brief クォータニオンから生成します
	 */
	void setRotationQuaternion( const Quaternion& );

	/**
	 * @brief 行列の補完をセットします。
	 */
	void setSlerp( const Matrix3x4& a, const Matrix3x4& b, float t );

	/**
	 * @brief 単位行列にします
	 */
	void identity();

	/**
	 * @brief 平行移動行列ショートカット
	 */
	void translate( float x, float y, float z );

	/**
	 * @brief 平行移動行列ショートカット
	 */
	void translate( const Vector3& v );

	/**
	 * @brief
	 */
	void rotateX( float x );

	/**
	 * @brief
	 */
	void rotateY( float y );

	/**
	 * @brief
	 */
	void rotateZ( float z );

	/**
	 * @brief
	 */
	void scale( float xyz );

	/**
	 * @brief
	 */
	void scale( float x, float y, float z );

	/**
	 * @brief
	 */
	void scale( const Vector3& a );

	/**
	 * @brief
	 */
	void multiply( const Vector3& a, Vector3* out ) const;

	/**
	 * @brief
	 */
	void multiply33( const Vector3& a, Vector3* out ) const;

	/**
	 * @brief 自身の逆行列を設定します
	 */
	void invert();

	/**
	 * @brief 自身を3x3行列とみなして転置行列を設定します
	 */
	void transpose33();

	/**
	 *
	 */
	void rotationQuaternion( const Quaternion& );
};

} // namespace Math
} // namespace NTEngine

#endif // INCLUDED_NTENGINE_MATH_MATRIX3X4_H
